package com.collect.collect.api.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.collect.collect.api.constant.Constants;
import com.collect.collect.api.entity.ApiLog;
import com.collect.collect.api.entity.HospitalList;
import com.collect.collect.api.enums.ApiNameEnum;
import com.collect.collect.api.exceptions.ApiDataException;
import com.collect.collect.api.service.IApiLogService;
import com.collect.collect.api.service.IHospitalListService;
import com.collect.collect.api.service.IMasterService;
import com.collect.collect.api.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.sql.Wrapper;
import java.util.*;

@RestController
public class DataReceivingController {

    //医院标识key
    private static final String hospitalIdKey = "hospital_id";
    //数据库表名key
    private static final String tableNameKey = "tableName";
    //数据key
    private static final String dataKey = "data";
    //批量处理数据最大值
    private static final int batchNum = 10;

    //数据库类型 dm mssql
    private static final String databaseType = "mssql";

    @Autowired
    private IMasterService masterService;
    @Autowired
    private IHospitalListService hospitalListService;
    @Autowired
    private IApiLogService apiLogService;

    @PostMapping("/dataReceiving")
    public JSONObject dataReceiving(@RequestBody Map<String,Object> paramMap){
        JSONObject jsonObject = new JSONObject();
        ApiLog apiLog = new ApiLog();
        Date nowDate = new Date();

        if(paramMap.get(hospitalIdKey) == null){
            jsonObject.put("code",500);
            jsonObject.put("msg","医院标识不能为空！");
            return jsonObject;
        }
        String hospitalId = (String) paramMap.get(hospitalIdKey);

        try {

            if(paramMap.get(tableNameKey) == null){
                throw new ApiDataException("表标识不能为空！");
            }

            if(paramMap.get(dataKey) == null){
                throw new ApiDataException("待更新数据不能空！");
            }

            String tableName = (String) paramMap.get(tableNameKey);

            //记录接口调用对象
            apiLog = new ApiLog(getApiName(tableName),getSonType(tableName),hospitalId,null, Constants.SUCCESS,tableName);

            HospitalList hospital = hospitalListService.selectHospitalListById(hospitalId);
            if(hospital == null){
                throw new ApiDataException("医院ID有误！");
            }

            apiLog.setHospitalName(hospital.getHospitalName());

            List<Map<String, Object>> data = (List<Map<String, Object>>) paramMap.get(dataKey);

            Set<String> dataColumn;

            if("dm".equals(databaseType)){
                dataColumn = masterService.selectDmColumnList("模式名",tableName);
            }else if("mssql".equals(databaseType)){
                //表字段
                dataColumn = masterService.selectColumnList(tableName);
            } else {
                dataColumn = new HashSet<>();
            }


            if(StringUtils.isEmpty(dataColumn)){
                throw new ApiDataException("表不存在！");
            }

            for(Map<String, Object> dataMap : data){
                //筛选删除没有的字段
                dataMap.entrySet().removeIf(next -> !dataColumn.contains(next.getKey()));

                dataMap.put("api_date",nowDate);
            }

            //分批插入
            int result = insertBatch(data, tableName);

            jsonObject.put("code",200);
            jsonObject.put("msg","同步成功！条数：" + result);
            apiLog.setReason("同步成功！条数：" + result);

        }catch (Exception e){
            jsonObject.put("code",500);
            jsonObject.put("msg","同步失败！错误：" + e.getMessage());

            //set错误日志
            apiLog.setReason("同步失败！错误：" + e.getMessage());
            apiLog.setIsSuccess(Constants.FAIL);
        }finally {
            HospitalList hospitalList = new HospitalList();
            hospitalList.setId(hospitalId);
            hospitalList.setEndDate(nowDate);
            //更新医院最后上传时间
            hospitalListService.updateHospitalList(hospitalList);

            //新增日志
            if(StringUtils.isNotBlank(apiLog.getApiName())) {
                apiLogService.insertApiLog(apiLog);
            }
        }
        return jsonObject;
    }

    /**
     * 主类型
     * @param tableName
     * @return
     */
    public String getApiName(String tableName){

        if("t_check_Pat".equalsIgnoreCase(tableName)){
            return ApiNameEnum.check_pat.getApiName();
        }else if("t_check_images".equalsIgnoreCase(tableName)){
            return ApiNameEnum.check_img.getApiName();
        }else if("t_check_Pathology".equalsIgnoreCase(tableName)){
            return ApiNameEnum.check_pathology.getApiName();
        }else if("t_pat_opertion".equalsIgnoreCase(tableName)){
            return ApiNameEnum.pat_operation.getApiName();
        }else if("t_rec_record".equalsIgnoreCase(tableName)){
            return ApiNameEnum.rec_record.getApiName();
        }else if("t_pat_jghpara".equalsIgnoreCase(tableName)){
            return ApiNameEnum.pat_structural.getApiName();
        }else if("v_pat_clearinfo".equalsIgnoreCase(tableName)){
            return ApiNameEnum.pat_clearInfo.getApiName();
        }

        return null;
    }

    /**
     * 子类型
     * @param tableName
     * @return
     */
    public String getSonType(String tableName){

        if("t_check_Pat".equalsIgnoreCase(tableName)){
            return ApiNameEnum.check_pat.getApiName();
        }else if("t_check_images".equalsIgnoreCase(tableName)){
            return ApiNameEnum.check_img.getApiName();
        }else if("t_check_Pathology".equalsIgnoreCase(tableName)){
            return ApiNameEnum.check_pathology.getApiName();
        }else if("t_pat_opertion".equalsIgnoreCase(tableName)){
            return ApiNameEnum.pat_operation.getApiName();
        }else if("t_rec_record".equalsIgnoreCase(tableName)){
            return ApiNameEnum.rec_record.getApiName();
        }else if("t_pat_jghpara".equalsIgnoreCase(tableName)){
            //todo 判断哪个类型结构化
            return null;
        }else if("v_pat_clearinfo".equalsIgnoreCase(tableName)){
            return ApiNameEnum.pat_clearInfo.getApiName();
        }
        return null;
    }

    /**
     * 批量插入，当数据量超过batchNum，分配插入
     * @param data 数据
     * @param tableName 表名
     */
    public int insertBatch(List<Map<String, Object>> data,String tableName){
        int result = 0;

        // 总数据量
        int insertLength = data.size();
        int i = 0;
        while (insertLength > batchNum) {
            result += masterService.insertMapDataList(data.subList(i, i + batchNum), tableName);
            i = i + batchNum;
            insertLength = insertLength - batchNum;
        }

        // 保存首次或最后一次数据量不足"批次最大保存数量"的数据
        if (insertLength > 0) {
            result += masterService.insertMapDataList(data.subList(i, i + insertLength),tableName);
        }

        return result;
    }
}
